/******************************************************************************/
/*  Files to Include                                                          */
/******************************************************************************/

#include <plib.h>           /* Include to use PIC32 peripheral libraries      */
#include <stdint.h>         /* For uint32_t definition                        */
#include <stdbool.h>        /* For true/false definition                      */

#include "system.h"         /* System funct/params, like osc/periph config    */
#include "user.h"           /* User funct/params, such as InitApp             */

/******************************************************************************/
/* Global Variable Declaration                                                */
/******************************************************************************/

/* i.e. uint32_t <variable_name>; */

/******************************************************************************/
/* Main Program                                                               */
/******************************************************************************/

int32_t main(void)
{

#ifndef PIC32_STARTER_KIT
    /*The JTAG is on by default on POR.  A PIC32 Starter Kit uses the JTAG, but
    for other debug tool use, like ICD 3 and Real ICE, the JTAG should be off
    to free up the JTAG I/O */
    DDPCONbits.JTAGEN = 0;
#endif

    /*Refer to the C32 peripheral library compiled help file for more
    information on the SYTEMConfig function.
    
    This function sets the PB divider, the Flash Wait States, and the DRM
    /wait states to the optimum value.  It also enables the cacheability for
    the K0 segment.  It could has side effects of possibly alter the pre-fetch
    buffer and cache.  It sets the RAM wait states to 0.  Other than
    the SYS_FREQ, this takes these parameters.  The top 3 may be '|'ed
    together:
    
    SYS_CFG_WAIT_STATES (configures flash wait states from system clock)
    SYS_CFG_PB_BUS (configures the PB bus from the system clock)
    SYS_CFG_PCACHE (configures the pCache if used)
    SYS_CFG_ALL (configures the flash wait states, PB bus, and pCache)*/

    /* TODO Add user clock/system configuration code if appropriate.  */
    SYSTEMConfig(SYS_FREQ, SYS_CFG_ALL); 

    /* Initialize I/O and Peripherals for application */
    InitApp();

    /*Configure Multivector Interrupt Mode.  Using Single Vector Mode
    is expensive from a timing perspective, so most applications
    should probably not use a Single Vector Mode*/
    INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);

    /* TODO <INSERT USER APPLICATION CODE HERE> */
#define PHOTOCELL_LIGHT 0x1
#define PHOTOCELL_AD_LIGHT 0x1
#define PHOTOCELL_DARK 0x0
#define PHOTOCELL_AD_DARK 0x0
#define LIGHT_ON 0x1
#define LIGHT_OFF 0x0

    
    static uint32_t photocell_value = PHOTOCELL_LIGHT;

    static uint32_t read_photocell(void);
    static uint32_t read_photocell(void) {
        // Request A/D converter read in value
        start_ad_converter();
        // Wait for A/D converter to be ready
        while(read_ad_status != 1);
        // Read in A/D converter value
        uint32_t photocell_ad_val = read_ad_val();
        // Determine whether the value is currently light or dark
        photocell_value = (photocell_ad_val > PHOTOCELL_AD_LIGHT) ?
                PHOTOCELL_LIGHT : PHOTOCELL_DARK;

        return photocell_value;
    }


    static void switch_light(uint32_t state) {
        // Change the GPIO value to the appropriate one
    }


    void control_light(void);
    void control_light(void) {
        static int32_t num_min_on = 0;
        static int32_t light_state = LIGHT_OFF;
        static int32_t light_duration = 480;

        if(light_state == LIGHT_OFF) {
            if(read_photocell() == PHOTOCELL_DARK) {
                switch_light(LIGHT_ON);
                num_min_on = light_duration;
            }
        }
        else {
            if(num_min_on-- == 0) {
                switch_light(LIGHT_OFF);
                // Wait ten seconds before checking the photocell again to see
                // whether it's still dark out
                sleep(10);
                // It's still dark out.  Add 30 minutes to the next light
                //  duration cycle.
                if(read_photocell() == PHOTOCELL_DARK) {
                    light_duration += 30;
                }
                // It's light out.  Subtract 30 minutes from the next light
                //  duration cycle.
                else {
                    light_duration -= 30;
                }
            }
        }
    }


    while(1)
    {
        // What should the microcontroller do every loop?
        //  1.  Check the value of the photocell and store it.
        //  2.  Act on the received data.
        //  3.  Go to sleep for one minute.
        control_light();
        sleep(60);
    }
}
